#include "script/ScriptDocumentOperation.h"

using namespace simodo;


variable::Value makeGotoDefinitionResponse(const std::u16string & uri, const lsp::Range & range) {
    return variable::Object {{
        { u"uri", uri },
        { u"range", lsp::DocumentContext::makeRange(range) },
    }};
}

/// \see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_declaration
variable::Value ScriptDocumentOperation::produceGotoDeclarationResponse(const lsp::Position & pos) const
{
    return produceGotoDefinitionResponse(pos);
}

/// \see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition
variable::Value ScriptDocumentOperation::produceGotoDefinitionResponse(const lsp::Position & pos) const {
    for (const auto & [v, loc] : _semantic_data.used())
        if (isOnToken(loc, pos)) {
            std::u16string uri = v.location().uri_index() < _files.size()
                                 ? inout::toU16(_files[v.location().uri_index()])
                                 : inout::toU16(_doc.file_name());
            return makeGotoDefinitionResponse(uri, v.location().range());
        }

    for (const auto & [t, ref] : _semantic_data.refs())
        if (isOnToken(t.location(), pos)) {
            return makeGotoDefinitionResponse(ref, {{ 0, 0 },
                                                    { 0, 0 }});
        }

    return { };
}
